﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RiskMan.DataClass.Models.Quik
{
    /// <summary>
    /// Расчет греков для опционов
    /// </summary>
    class Greek
    {

        public static void GetGammaAndDelta(CurrentParamModel curParam)
        {

            int yearLen = 365;
            var pi = 3.1415926535897932384626433832795;

            var pSigma = curParam.Volatility / 100;
            var pTmt = curParam.DaystoMatDate / yearLen;
            var d1 = Math.Log(curParam.SettlePrice / curParam.Strike);
            var tmp1 = (pSigma * pSigma * 0.5) * pTmt;
            var tmp2 = Math.Sqrt(pTmt) * pSigma;
            d1 = (d1 + tmp1) / tmp2;
            tmp1 = Math.Exp((-1 * 0 / 100) * pTmt);

            if (curParam.OptionType == "Call")
                curParam.Delta = tmp1 * GetNormDist(d1);
            else
                curParam.Delta = -1 * tmp1 * GetNormDist(-1 * d1);


            var tmp3 = Math.Exp(-0.5 * d1 * d1) / Math.Sqrt(2 * pi);
            var tmp4 = curParam.SettlePrice * tmp2;
            curParam.Gamma = 100 * tmp3 / tmp4;


        }

        /// <summary>
        /// Function calculation normal distribution
        /// </summary>
        /// <param name="tmp"></param>
        /// <returns></returns>
        public static double GetNormDist(double tmp)
        {

            if (tmp > 10)
                return 1;

            if (tmp < -10)
                return 0;

            var ax = Math.Abs(tmp);
            var t = 1 / (1 + 0.2316419 * ax);
            var d = 0.3989423 * Math.Exp(-0.5 * tmp * tmp);
            var p = d * t * ((((1.330274 * t - 1.821256) * t + 1.781478) * t - 0.3565638) * t + 0.3193815);
            if (tmp > 0)
                return 1 - p;


            return 0;
        }
    }
}
